package com.ruoyi.oss.service.impl;

import cn.hutool.core.io.file.FileNameUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.oss.dao.SysOssDao;
import com.ruoyi.oss.domain.SysOss;
import com.ruoyi.oss.domain.bo.SysOssSearchListBo;
import com.ruoyi.oss.domain.bo.UploadResult;
import com.ruoyi.oss.ienum.OssType;
import com.ruoyi.oss.mapper.SysOssMapper;
import com.ruoyi.oss.service.CloudOssService;
import com.ruoyi.oss.service.SysOssDownloadRecordsService;
import com.ruoyi.oss.service.SysOssService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;

/**
 * oss文件存储
 *
 * @author xueyu
 */
@Service
@Slf4j
public class SysOssServiceImpl extends ServiceImpl<SysOssMapper, SysOss> implements SysOssService {

    private SysOssDao sysOssDao;

    private CloudOssService cloudOssService;

    private SysOssDownloadRecordsService sysOssDownloadRecordsService;

    @Autowired
    public void setSysOssDownloadRecordsService(SysOssDownloadRecordsService sysOssDownloadRecordsService) {
        this.sysOssDownloadRecordsService = sysOssDownloadRecordsService;
    }

    @Autowired
    public void setCloudOssService(CloudOssService cloudOssService) {
        this.cloudOssService = cloudOssService;
    }

    @Autowired
    public void setSysOssDao(SysOssDao sysOssDao) {
        this.sysOssDao = sysOssDao;
    }

    /**
     * 查询文件上传记录
     *
     * @param searchBo   查询文件上传记录搜索条件
     * @param pageDomain 分页参数
     * @return 文件上传记录参数
     */
    @Override
    public Page<SysOss> pageList(SysOssSearchListBo searchBo, PageDomain pageDomain) {
        Page<SysOss> page = PageUtils.buildPagePlus(pageDomain);
        LambdaQueryWrapper<SysOss> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNoneBlank(searchBo.getFileName()), SysOss::getFileName, searchBo.getFileName());
        queryWrapper.like(StringUtils.isNotBlank(searchBo.getOriginalName()), SysOss::getOriginalName, searchBo.getOriginalName());
        queryWrapper.eq(StringUtils.isNotBlank(searchBo.getFileSuffix()), SysOss::getFileSuffix, searchBo.getFileSuffix());
        queryWrapper.eq(StringUtils.isNotBlank(searchBo.getUrl()), SysOss::getUrl, searchBo.getUrl());
        queryWrapper.eq(StringUtils.isNotBlank(searchBo.getOssService()), SysOss::getOssService, searchBo.getOssService());
        page = baseMapper.selectPage(page, queryWrapper);
        return page;
    }

    /**
     * 上传oss文件
     *
     * @param multipartFile 多部份文件
     * @return oss上传记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysOss upload(MultipartFile multipartFile) {
        //文件的原始名称
        String originalFilename = multipartFile.getOriginalFilename();
        //文件大小
        long fileSize = multipartFile.getSize();
        String fileSuffix = FileNameUtil.getSuffix(originalFilename);
        //上传文件至oss
        try {
            UploadResult uploadResult = cloudOssService.upload(multipartFile, fileSuffix);
            SysOss sysOss = new SysOss();
            String fileName = uploadResult.getFileName();
            sysOss.setFileName(fileName);
            String bucketName = uploadResult.getBucketName();
            sysOss.setBucketName(bucketName);
            sysOss.setOriginalName(originalFilename);
            sysOss.setFileSuffix(fileSuffix);
            sysOss.setUrl(uploadResult.getUrl());
            OssType ossType = uploadResult.getOssType();
            sysOss.setOssService(ossType.name());
            sysOss.setFileSize(fileSize);
            String ossPath = uploadResult.getOssPath();
            sysOss.setOssPath(ossPath);
            return sysOssDao.save(sysOss);
        } catch (IOException e) {
            throw new ServiceException("上传文件失败，请重试!");
        }
    }


    /**
     * 根据id查询数据
     *
     * @param id id
     * @return 文件上传记录
     */
    @Override
    public SysOss findById(Long id) {
        return sysOssDao.findById(id).orElse(null);
    }


    /**
     * 下载文件
     *
     * @param sysOss              文件上传记录
     * @param httpServletRequest  请求
     * @param httpServletResponse 响应
     * @return 响应体
     */
    @Override
    public ResponseEntity<StreamingResponseBody> download(SysOss sysOss, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        try {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            Long userId = loginUser.getUserId();
            CompletableFuture.runAsync(() -> sysOssDownloadRecordsService.recordDownload(userId, sysOss, httpServletRequest));
        } catch (Exception ignored) {
        }
        return cloudOssService.download(sysOss, httpServletRequest, httpServletResponse);
    }
}
